#include <chrono>
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

using std::cout;
using std::endl;
using std::thread;
using std::mutex;
using std::unique_lock;
using std::condition_variable;

//两个线程A与B，A线程设置共享数据，B线程消费共享数据；当A线程将
//共享数据设置完毕之后，通知B线程，让B线程进行消费，也就是
//A线程设置数据然后B线程消费数据
class Example
{
public:
    void threadFuncA()
    {
        for(int idx = 0; idx < 10; ++idx)
        {
            //让A线程进来之后先睡眠
            std::this_thread::sleep_for(std::chrono::milliseconds(2));
            _data = idx;
            _flag = true;
            _cond.notify_one();//唤醒线程
        }
    }

    void threadFuncB()
    {
        for(int idx = 0; idx < 10; ++idx)
        {
            unique_lock<mutex> ul(_mtx);
            if(!_flag)
            {
                //在执行wait之前一定要抢夺锁，然后在睡眠之前要释放锁
                _cond.wait(ul);
                //在条件变量上睡眠的线程如果被唤醒了，是需要继续抢夺
                //锁的，只有抢夺成功，才能让函数wait返回，如果抢夺失败
                //还是会等待获取锁
            }
            cout << "get data = " << _data << endl;
            _flag = false;
        }
    }
private:
    int _data;//共享的数据
    bool _flag;//标志位
    mutex _mtx;//互斥锁
    condition_variable _cond;//条件变量
};

int main(int argc, char *argv[])
{
    Example ex;
    thread thA(&Example::threadFuncA, &ex);//创建线程A
    thread thB(&Example::threadFuncB, &ex);//创建线程B

    //让主线程阻塞等待线程A与线程B
    thA.join();
    thB.join();
    return 0;
}

